package com.ssy.lingxi.pay.serviceimpl.assetAccount;

import cn.hutool.core.bean.BeanUtil;
import com.github.binarywang.wxpay.bean.order.WxPayMwebOrderResult;
import com.ssy.lingxi.common.constant.Constants;
import com.ssy.lingxi.common.constant.member.MemberLevelTypeEnum;
import com.ssy.lingxi.common.constant.member.MemberStatusEnum;
import com.ssy.lingxi.common.constant.member.MemberTypeEnum;
import com.ssy.lingxi.common.constant.order.OrderPayChannelEnum;
import com.ssy.lingxi.common.constant.order.OrderPaymentParameterEnum;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.model.vo.PageVO;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.component.rabbitMQ.constants.MessageConstants;
import com.ssy.lingxi.component.rabbitMQ.service.IRabbitMQUtils;
import com.ssy.lingxi.component.redis.service.IRedisStringUtils;
import com.ssy.lingxi.component.redis.utils.SerialNumberUtils;
import com.ssy.lingxi.member.merchant.api.constant.MemberPayPasswordCheckEnum;
import com.ssy.lingxi.member.merchant.api.feign.inner.MemberInnerControllerFeign;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.request.MemberFeignPayPswCheckVO;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.response.MemberFeignPayPswCheckResultVO;
import com.ssy.lingxi.message.api.constant.MessageTemplateCode;
import com.ssy.lingxi.message.api.feign.SystemMessageControllerFeign;
import com.ssy.lingxi.message.api.vo.request.SystemMessageRequest;
import com.ssy.lingxi.order.api.feign.OrderFeignService;
import com.ssy.lingxi.order.api.model.vo.request.OrderPayChannelFeignVO;
import com.ssy.lingxi.order.api.model.vo.request.OrderPayParameterFeignVO;
import com.ssy.lingxi.order.api.model.vo.response.PaymentParameterFeignDetailVO;
import com.ssy.lingxi.pay.api.common.AccountTypeEnum;
import com.ssy.lingxi.pay.api.common.ServiceTypeEnum;
import com.ssy.lingxi.pay.api.dto.request.MobilePayRequest;
import com.ssy.lingxi.pay.api.dto.request.assetAccount.*;
import com.ssy.lingxi.pay.api.dto.response.assetAccount.*;
import com.ssy.lingxi.pay.common.AccountStatusEnum;
import com.ssy.lingxi.pay.common.PayTypeEnum;
import com.ssy.lingxi.pay.common.TradeOperationEnum;
import com.ssy.lingxi.pay.common.TradeStatusEnum;
import com.ssy.lingxi.pay.entity.assetAccount.AccountCashOutRecord;
import com.ssy.lingxi.pay.entity.assetAccount.AccountStatusRecord;
import com.ssy.lingxi.pay.entity.assetAccount.AccountTradeRecord;
import com.ssy.lingxi.pay.entity.assetAccount.MemberAssetAccount;
import com.ssy.lingxi.pay.model.assetAccount.MemberAssetAccountQuery;
import com.ssy.lingxi.pay.model.assetAccount.PayResult;
import com.ssy.lingxi.pay.repository.assetAccount.AccountCashOutRecordRepository;
import com.ssy.lingxi.pay.repository.assetAccount.AccountStatusRecordRepository;
import com.ssy.lingxi.pay.repository.assetAccount.AccountTradeRecordRepository;
import com.ssy.lingxi.pay.repository.assetAccount.MemberAssetAccountRepository;
import com.ssy.lingxi.pay.service.IPayCacheService;
import com.ssy.lingxi.pay.service.IWeChatPayService;
import com.ssy.lingxi.pay.service.assetAccount.IMemberAssetAccountService;
import com.ssy.lingxi.report.api.enums.AccountOperateTypeEnum;
import com.ssy.lingxi.report.api.enums.OperateDataSourceEnum;
import com.ssy.lingxi.report.api.feign.ReportControllerFeign;
import com.ssy.lingxi.report.api.vo.request.OperateNoticeVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import javax.servlet.http.HttpServletRequest;
import java.text.DecimalFormat;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 会员资金账户
 * @author jw.chen
 * @version 2.0.0
 * @date 2020/7/21
 */
@Service
public class MemberAssetAccountServiceImpl implements IMemberAssetAccountService {
    private static final Logger logger = LoggerFactory.getLogger(MemberAssetAccountServiceImpl.class);

    @Resource
    private IPayCacheService payCacheService;

    @Resource
    private MemberAssetAccountRepository memberAssetAccountRepository;

    @Resource
    private AccountTradeRecordRepository accountTradeRecordRepository;

    @Resource
    private AccountStatusRecordRepository accountStatusRecordRepository;

    @Resource
    private AccountCashOutRecordRepository accountCashOutRecordRepository;

    @Resource
    private IWeChatPayService weChatPayService;

    @Resource
    private MemberInnerControllerFeign memberInnerControllerFeign;

    @Resource
    private OrderFeignService orderFeignService;

    @Resource
    private IRedisStringUtils redisStringUtils;

    @Resource
    private IRabbitMQUtils rabbitMQUtils;

    @Resource
    private ReportControllerFeign reportControllerFeign;

    @Resource
    private SystemMessageControllerFeign systemMessageControllerFeign;

    /**
     * 查询会员资金账户列表
     * @param pageVO 分页参数
     * @param memberAssetAccountMiddle 接口参数
     * @return 查询结果
     */
    @Override
    public Page<MemberAssetAccount> getMemberAssetAccountList(PageVO pageVO, MemberAssetAccountQuery memberAssetAccountMiddle) {
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize());
        return memberAssetAccountRepository.findAll(getSpecification(memberAssetAccountMiddle), page);
    }

    /**
     * 查询会员资金账户
     * @param id 账户Id
     * @return MemberAssetAccount
     */
    @Override
    public MemberAssetAccount getMemberAssetAccount(Long id) {
        return memberAssetAccountRepository.findById(id).orElse(null);
    }

    /**
     * 添加会员资金账户
     * @param memberAssetAccountRequestList 账户列表
     * @return 提示信息
     */
    @Override
    public String saveOrUpdateMemberAssetAccount(List<MemberAssetAccount> memberAssetAccountRequestList) {
        List<MemberAssetAccount> memberAssetAccountList = memberAssetAccountRequestList.stream().map(memberAssetAccount -> {
            //获取参数
            Long id = memberAssetAccount.getId();
            //判断是新增还是修改
            if (id != null && id > 0) {
                MemberAssetAccount current_memberAssetAccount = memberAssetAccountRepository.findById(id).orElse(null);
                if (current_memberAssetAccount != null) {
                    BeanUtils.copyProperties(current_memberAssetAccount, memberAssetAccount);
                    return memberAssetAccount;
                } else {
                    throw new BusinessException(ResponseCode.PAY_MEMBER_ASSET_ACCOUNT_NOT_EXIST);
                }
            } else {
                //存在的会员资金账户不再新增
                Long memberId = memberAssetAccount.getMemberId();
                Long memberRoleId = memberAssetAccount.getMemberRoleId();
                Long parentMemberId = memberAssetAccount.getParentMemberId();
                Long parentMemberRoleId = memberAssetAccount.getParentMemberRoleId();
                MemberAssetAccount existMemberAssetAccount = memberAssetAccountRepository.findFirstByMemberIdAndMemberRoleIdAndParentMemberIdAndParentMemberRoleId(memberId, memberRoleId, parentMemberId, parentMemberRoleId);
                if (existMemberAssetAccount == null) {
                    //初始化数据
                    Double defaultMoney = 0.00;
                    String defaultMoneyEncrypt = DigestUtils.md5DigestAsHex(String.valueOf(defaultMoney).getBytes());
                    memberAssetAccount.setAccountBalance(defaultMoney);
                    memberAssetAccount.setAccountBalanceEncrypt(defaultMoneyEncrypt);
                    memberAssetAccount.setLockBalance(defaultMoney);
                    memberAssetAccount.setLockBalanceEncrypt(defaultMoneyEncrypt);
                    memberAssetAccount.setAccountStatus(AccountStatusEnum.Thaw.getCode());
                    memberAssetAccount.setMemberStatus(AccountStatusEnum.Thaw.getCode());
                    memberAssetAccount.setCreateTime(System.currentTimeMillis());
                    return memberAssetAccount;
                } else {
                    return null;
                }
            }
        }).filter(Objects::nonNull).collect(Collectors.toList());
        if(memberAssetAccountList.size() > 0){
            //数据库持久化对象
            memberAssetAccountRepository.saveAll(memberAssetAccountList);
        }
        return ResponseCode.SUCCESS.getMessage();
    }

    /**
     * 修改会员资金账户状态
     * @param memberAssetAccountUpdateRequest 接口参数
     * @return 提示信息
     */
    @Override
    public String updateMemberAssetAccount(MemberAssetAccountUpdateRequest memberAssetAccountUpdateRequest) {
        Long memberId = memberAssetAccountUpdateRequest.getMemberId();
        Long memberRoleId = memberAssetAccountUpdateRequest.getMemberRoleId();
        Long parentMemberId = memberAssetAccountUpdateRequest.getParentMemberId();
        Long parentMemberRoleId = memberAssetAccountUpdateRequest.getParentMemberRoleId();
        Integer memberStatus = memberAssetAccountUpdateRequest.getMemberStatus();
        Integer memberType = memberAssetAccountUpdateRequest.getMemberType();
        List<MemberAssetAccount> memberAssetAccountList;
        if (AccountTypeEnum.Platform.getCode().equals(memberType)) {
            memberAssetAccountList = memberAssetAccountRepository.findByMemberIdAndMemberRoleId(memberId, memberRoleId);
        } else {
            memberAssetAccountList = memberAssetAccountRepository.findByMemberIdAndMemberRoleIdAndParentMemberIdAndParentMemberRoleId(memberId, memberRoleId, parentMemberId, parentMemberRoleId);
        }
        if (memberAssetAccountList != null && !memberAssetAccountList.isEmpty()) {
            memberAssetAccountList.forEach(memberAssetAccount -> memberAssetAccount.setMemberStatus(memberStatus));
            memberAssetAccountRepository.saveAll(memberAssetAccountList);
        }
        return "修改成功";
    }

    /**
     * 冻结/解冻账号
     * @param id 账户Id
     * @param status 状态
     * @return 提示信息
     */
    @Transactional
    @Override
    public String updateMemberAssetAccountEnable(Long id, Integer status, String remark) {
        if (!AccountStatusEnum.Thaw.getCode().equals(status) && !AccountStatusEnum.Frozen.getCode().equals(status)) {
            throw new BusinessException(ResponseCode.PAY_MEMBER_ASSET_ACCOUNT_STATUS_EXCEPTION);
        }
        //验证数据库中是否存在该数据
        MemberAssetAccount memberAssetAccount = memberAssetAccountRepository.findById(id).orElse(null);
        if (memberAssetAccount != null) {
            //持久化数据
            memberAssetAccount.setAccountStatus(status);
            memberAssetAccountRepository.saveAndFlush(memberAssetAccount);

            AccountStatusRecord accountStatusRecord = new AccountStatusRecord();
            accountStatusRecord.setOperation(status);
            accountStatusRecord.setStatus(status);
            accountStatusRecord.setCreateTime(System.currentTimeMillis());
            accountStatusRecord.setMemberAssetAccount(memberAssetAccount);
            accountStatusRecord.setRemark(remark);
            accountStatusRecordRepository.saveAndFlush(accountStatusRecord);
            return ResponseCode.SUCCESS.getMessage();
        }
        throw new BusinessException(ResponseCode.PAY_MEMBER_ASSET_ACCOUNT_NOT_EXIST);
    }

    /**
     * 资金账户充值
     * @param rechargeRequest 接口参数
     * @return 充值结果
     */
    @Transactional
    @Override
    public AccountRechargeResponse rechargeAssetAccount(HttpServletRequest request, RechargeRequest rechargeRequest) {
        Long memberAssetAccountId = rechargeRequest.getMemberAssetAccountId();
        Double money = rechargeRequest.getMoney();
        MemberAssetAccount memberAssetAccount = memberAssetAccountRepository.findById(memberAssetAccountId).orElse(null);
        if (memberAssetAccount != null) {
            //校验账户
            this.checkMemberAssetAccount(memberAssetAccount);

            //交易订单号
            String tradeCode = SerialNumberUtils.getNumber(redisStringUtils, Constants.ACCOUNT_TRACE_CODE, Constants.REDIS_ORDER_INDEX, Constants.ACCOUNT_TRACE_CODE_DATE, Constants.ACCOUNT_TRACE_CODE_NUM_LEN);
            DecimalFormat decimalFormat = new DecimalFormat("#.00");

            //获取会员支付参数
            Long parentMemberId = memberAssetAccount.getParentMemberId();
            Long parentMemberRoleId = memberAssetAccount.getParentMemberRoleId();

            MobilePayRequest mobilePayRequest = new MobilePayRequest();
            mobilePayRequest.setOrderCode(tradeCode);
            mobilePayRequest.setPayMoney(Double.parseDouble(decimalFormat.format(money)));
            mobilePayRequest.setRemark(TradeOperationEnum.AccountRecharge.getMessage());
            mobilePayRequest.setServiceType(ServiceTypeEnum.Pay_Recharge.getCode());
            mobilePayRequest.setMemberId(parentMemberId);
            mobilePayRequest.setMemberRoleId(parentMemberRoleId);

            //支付
            PayResult payResult;
            Integer memberLevelType = memberAssetAccount.getMemberLevelType();
            Wrapper<PaymentParameterFeignDetailVO> parameterResult;
            if (MemberLevelTypeEnum.PLATFORM.getCode().equals(memberLevelType)) {
                mobilePayRequest.setPayType(PayTypeEnum.Platform.getCode());
                OrderPayChannelFeignVO feignVO = new OrderPayChannelFeignVO();
                feignVO.setPayChannel(OrderPayChannelEnum.WECHAT_PAY);
                parameterResult = orderFeignService.findPlatformPaymentParameters(feignVO);
            } else {
                mobilePayRequest.setPayType(PayTypeEnum.Member.getCode());
                OrderPayParameterFeignVO feignVO = new OrderPayParameterFeignVO();
                feignVO.setMemberId(parentMemberId);
                feignVO.setRoleId(parentMemberRoleId);
                feignVO.setPayChannel(OrderPayChannelEnum.WECHAT_PAY);
                parameterResult = orderFeignService.findMemberPaymentParameters(feignVO);
            }

            if(CollectionUtils.isEmpty(parameterResult.getData().getParameters())) {
                throw new BusinessException(ResponseCode.PAY_PLATFORM_PARAMETERS_DOES_NOT_EXIST);
            }

            parameterResult.getData().getParameters().forEach(p -> {
                if(p.getParameter().equals(OrderPaymentParameterEnum.WECHAT_MERCHANT_ID)) {
                    mobilePayRequest.setMerchantId(p.getValue());
                } else if(p.getParameter().equals(OrderPaymentParameterEnum.WECHAT_APP_ID)) {
                    mobilePayRequest.setAppId(p.getValue());
                } else if(p.getParameter().equals(OrderPaymentParameterEnum.WECHAT_API_KEY)) {
                    mobilePayRequest.setApiKey(p.getValue());
                }
            });

            payResult = weChatPayService.nativePay(mobilePayRequest, request);

            if (payResult.isSuccess()) {
                //保存交易记录
                AccountTradeRecord accountTradeRecord = new AccountTradeRecord();
                accountTradeRecord.setTradeCode(tradeCode);
                accountTradeRecord.setTradeMoney(money);
                accountTradeRecord.setMemberAssetAccount(memberAssetAccount);
                accountTradeRecord.setOperation(TradeOperationEnum.AccountRecharge.getCode());
                accountTradeRecord.setStatus(TradeStatusEnum.Paying.getCode());
                accountTradeRecord.setRemark(TradeOperationEnum.AccountRecharge.getMessage());
                accountTradeRecord.setTradeTime(System.currentTimeMillis());
                accountTradeRecordRepository.saveAndFlush(accountTradeRecord);

                //发送消息到队列(2小时)
                Long accountTradeRecordId = accountTradeRecord.getId();
                rabbitMQUtils.sendMsg(MessageConstants.pay_recharge_exchange, MessageConstants.pay_recharge_routingKey, accountTradeRecordId, 7200 * 1000);

                //支付返回结果
                Map<String, String> body = (Map<String, String>) payResult.getBody();
                AccountRechargeResponse accountRechargeResponse = new AccountRechargeResponse();
                accountRechargeResponse.setCodeUrl(body.get("code_url"));
                accountRechargeResponse.setTradeRecordId(accountTradeRecordId);
                return accountRechargeResponse;
            } else {
                throw new BusinessException(ResponseCode.PAY_MEMBER_PAY_FAIL, payResult.getMessage());
            }
        } else {
            throw new BusinessException(ResponseCode.PAY_MEMBER_ASSET_ACCOUNT_NOT_EXIST);
        }
    }

    /**
     * 资金账户充值
     * @param rechargeRequest 接口参数
     * @return 充值结果
     */
    @Transactional
    @Override
    public AccountRechargeAppResponse rechargeAssetAccountApp(HttpServletRequest request, RechargeRequest rechargeRequest) {
        Long memberAssetAccountId = rechargeRequest.getMemberAssetAccountId();
        Double money = rechargeRequest.getMoney();
        MemberAssetAccount memberAssetAccount = memberAssetAccountRepository.findById(memberAssetAccountId).orElse(null);
        if (memberAssetAccount != null) {
            //校验账户
            this.checkMemberAssetAccount(memberAssetAccount);

            //交易订单号
            String tradeCode = SerialNumberUtils.getNumber(redisStringUtils, Constants.ACCOUNT_TRACE_CODE, Constants.REDIS_ORDER_INDEX, Constants.ACCOUNT_TRACE_CODE_DATE, Constants.ACCOUNT_TRACE_CODE_NUM_LEN);
            DecimalFormat decimalFormat = new DecimalFormat("#.00");

            //获取会员支付参数
            Long parentMemberId = memberAssetAccount.getParentMemberId();
            Long parentMemberRoleId = memberAssetAccount.getParentMemberRoleId();

            MobilePayRequest mobilePayRequest = new MobilePayRequest();
            mobilePayRequest.setOrderCode(tradeCode);
            mobilePayRequest.setPayMoney(Double.parseDouble(decimalFormat.format(money)));
            mobilePayRequest.setRemark(TradeOperationEnum.AccountRecharge.getMessage());
            mobilePayRequest.setServiceType(ServiceTypeEnum.Pay_Recharge.getCode());
            mobilePayRequest.setMemberId(parentMemberId);
            mobilePayRequest.setMemberRoleId(parentMemberRoleId);

            //支付
            PayResult payResult;
            Wrapper<PaymentParameterFeignDetailVO> parameterResult;
            Integer memberLevelType = memberAssetAccount.getMemberLevelType();
            if (MemberLevelTypeEnum.PLATFORM.getCode().equals(memberLevelType)) {
                mobilePayRequest.setPayType(PayTypeEnum.Platform.getCode());
                OrderPayChannelFeignVO feignVO = new OrderPayChannelFeignVO();
                feignVO.setPayChannel(OrderPayChannelEnum.WECHAT_PAY);
                parameterResult = orderFeignService.findPlatformPaymentParameters(feignVO);
            } else {
                mobilePayRequest.setPayType(PayTypeEnum.Member.getCode());
                OrderPayParameterFeignVO feignVO = new OrderPayParameterFeignVO();
                feignVO.setMemberId(parentMemberId);
                feignVO.setRoleId(parentMemberRoleId);
                feignVO.setPayChannel(OrderPayChannelEnum.WECHAT_PAY);
                parameterResult = orderFeignService.findMemberPaymentParameters(feignVO);
            }

            if(CollectionUtils.isEmpty(parameterResult.getData().getParameters())) {
                throw new BusinessException(ResponseCode.PAY_PLATFORM_PARAMETERS_DOES_NOT_EXIST);
            }

            parameterResult.getData().getParameters().forEach(p -> {
                if(p.getParameter().equals(OrderPaymentParameterEnum.WECHAT_MERCHANT_ID)) {
                    mobilePayRequest.setMerchantId(p.getValue());
                } else if(p.getParameter().equals(OrderPaymentParameterEnum.WECHAT_APP_ID)) {
                    mobilePayRequest.setAppId(p.getValue());
                } else if(p.getParameter().equals(OrderPaymentParameterEnum.WECHAT_API_KEY)) {
                    mobilePayRequest.setApiKey(p.getValue());
                }
            });

            payResult = weChatPayService.appPay(mobilePayRequest, request);
            if (payResult.isSuccess()) {
                //保存交易记录
                AccountTradeRecord accountTradeRecord = new AccountTradeRecord();
                accountTradeRecord.setTradeCode(tradeCode);
                accountTradeRecord.setTradeMoney(money);
                accountTradeRecord.setMemberAssetAccount(memberAssetAccount);
                accountTradeRecord.setOperation(TradeOperationEnum.AccountRecharge.getCode());
                accountTradeRecord.setStatus(TradeStatusEnum.Paying.getCode());
                accountTradeRecord.setRemark(TradeOperationEnum.AccountRecharge.getMessage());
                accountTradeRecord.setTradeTime(System.currentTimeMillis());
                accountTradeRecordRepository.saveAndFlush(accountTradeRecord);

                //发送消息到队列(2小时)
                Long accountTradeRecordId = accountTradeRecord.getId();
                rabbitMQUtils.sendMsg(MessageConstants.pay_recharge_exchange, MessageConstants.pay_recharge_routingKey, accountTradeRecordId, 7200 * 1000);

                //支付返回结果
                Map<String, String> body = (Map<String, String>) payResult.getBody();
                AccountRechargeAppResponse accountRechargeAppResponse = new AccountRechargeAppResponse();
                accountRechargeAppResponse.setNoncestr(body.get("noncestr"));
                accountRechargeAppResponse.setPartnerid(body.get("partnerid"));
                accountRechargeAppResponse.setPrepayid(body.get("prepayid"));
                accountRechargeAppResponse.setSign(body.get("sign"));
                accountRechargeAppResponse.setTimestamp(body.get("timestamp"));
                accountRechargeAppResponse.setTradeRecordId(accountTradeRecordId);
                return accountRechargeAppResponse;
            } else {
                throw new BusinessException(ResponseCode.PAY_MEMBER_PAY_FAIL, payResult.getMessage());
            }
        } else {
            throw new BusinessException(ResponseCode.PAY_MEMBER_ASSET_ACCOUNT_NOT_EXIST);
        }
    }

    /**
     * 资金账户充值(H5)
     * @param request
     * @param rechargeJsApiRequest
     * @return
     */
    @Override
    public AccountRechargeJsApiResponse rechargeAssetAccountJsApi(HttpServletRequest request, RechargeJsApiRequest rechargeJsApiRequest) {
        Long memberAssetAccountId = rechargeJsApiRequest.getMemberAssetAccountId();
        Double money = rechargeJsApiRequest.getMoney();
        MemberAssetAccount memberAssetAccount = memberAssetAccountRepository.findById(memberAssetAccountId).orElse(null);
        if (memberAssetAccount != null) {
            //校验账户
            this.checkMemberAssetAccount(memberAssetAccount);

            //交易订单号
            String tradeCode = SerialNumberUtils.getNumber(redisStringUtils, Constants.ACCOUNT_TRACE_CODE, Constants.REDIS_ORDER_INDEX, Constants.ACCOUNT_TRACE_CODE_DATE, Constants.ACCOUNT_TRACE_CODE_NUM_LEN);
            DecimalFormat decimalFormat = new DecimalFormat("#.00");

            //获取会员支付参数
            Long parentMemberId = memberAssetAccount.getParentMemberId();
            Long parentMemberRoleId = memberAssetAccount.getParentMemberRoleId();

            MobilePayRequest mobilePayRequest = new MobilePayRequest();
            mobilePayRequest.setOrderCode(tradeCode);
            mobilePayRequest.setPayMoney(Double.parseDouble(decimalFormat.format(money)));
            mobilePayRequest.setRemark(TradeOperationEnum.AccountRecharge.getMessage());
            mobilePayRequest.setServiceType(ServiceTypeEnum.Pay_Recharge.getCode());
            mobilePayRequest.setMemberId(parentMemberId);
            mobilePayRequest.setMemberRoleId(parentMemberRoleId);

            //支付
            PayResult payResult;
            Wrapper<PaymentParameterFeignDetailVO> parameterResult;
            Integer memberLevelType = memberAssetAccount.getMemberLevelType();
            if (MemberLevelTypeEnum.PLATFORM.getCode().equals(memberLevelType)) {
                mobilePayRequest.setPayType(PayTypeEnum.Platform.getCode());
                OrderPayChannelFeignVO feignVO = new OrderPayChannelFeignVO();
                feignVO.setPayChannel(OrderPayChannelEnum.WECHAT_PAY);
                parameterResult = orderFeignService.findPlatformPaymentParameters(feignVO);
            } else {
                mobilePayRequest.setPayType(PayTypeEnum.Member.getCode());
                OrderPayParameterFeignVO feignVO = new OrderPayParameterFeignVO();
                feignVO.setMemberId(parentMemberId);
                feignVO.setRoleId(parentMemberRoleId);
                feignVO.setPayChannel(OrderPayChannelEnum.WECHAT_PAY);
                parameterResult = orderFeignService.findMemberPaymentParameters(feignVO);
            }

            if(CollectionUtils.isEmpty(parameterResult.getData().getParameters())) {
                throw new BusinessException(ResponseCode.PAY_PLATFORM_PARAMETERS_DOES_NOT_EXIST);
            }

            parameterResult.getData().getParameters().forEach(p -> {
                if(p.getParameter().equals(OrderPaymentParameterEnum.WECHAT_MERCHANT_ID)) {
                    mobilePayRequest.setMerchantId(p.getValue());
                } else if(p.getParameter().equals(OrderPaymentParameterEnum.WECHAT_APP_ID)) {
                    mobilePayRequest.setAppId(p.getValue());
                } else if(p.getParameter().equals(OrderPaymentParameterEnum.WECHAT_API_KEY)) {
                    mobilePayRequest.setApiKey(p.getValue());
                }
            });

            payResult = weChatPayService.h5Pay(mobilePayRequest, request);
            if (payResult.isSuccess()) {
                //保存交易记录
                AccountTradeRecord accountTradeRecord = new AccountTradeRecord();
                accountTradeRecord.setTradeCode(tradeCode);
                accountTradeRecord.setTradeMoney(money);
                accountTradeRecord.setOperation(TradeOperationEnum.AccountRecharge.getCode());
                accountTradeRecord.setStatus(TradeStatusEnum.Paying.getCode());
                accountTradeRecord.setRemark(TradeOperationEnum.AccountRecharge.getMessage());
                accountTradeRecord.setTradeTime(System.currentTimeMillis());
                AccountTradeRecord temp = accountTradeRecordRepository.saveAndFlush(accountTradeRecord);
                accountTradeRecord.setMemberAssetAccount(memberAssetAccount);
                accountTradeRecordRepository.saveAndFlush(temp);
                //发送消息到队列(2小时)
                Long accountTradeRecordId = accountTradeRecord.getId();
                rabbitMQUtils.sendMsg(MessageConstants.pay_recharge_exchange, MessageConstants.pay_recharge_routingKey, accountTradeRecordId, 7200 * 1000);

                //支付返回结果
                Object obj = payResult.getBody();
                if (obj instanceof WxPayMwebOrderResult) {
                    WxPayMwebOrderResult result = (WxPayMwebOrderResult)obj;
                    AccountRechargeJsApiResponse accountRechargeJsApiResponse = new AccountRechargeJsApiResponse();
                    accountRechargeJsApiResponse.setMwebUrl(result.getMwebUrl());
                    accountRechargeJsApiResponse.setTradeCode(tradeCode);
                    accountRechargeJsApiResponse.setAccountTradeRecordId(accountTradeRecordId);
                    return accountRechargeJsApiResponse;
                }
                throw new BusinessException(ResponseCode.PAY_MEMBER_PAY_FAIL, payResult.getMessage());
            } else {
                throw new BusinessException(ResponseCode.PAY_MEMBER_PAY_FAIL, payResult.getMessage());
            }
        } else {
            throw new BusinessException(ResponseCode.PAY_MEMBER_ASSET_ACCOUNT_NOT_EXIST);
        }
    }

    /**
     * 资金账户充值(小程序)
     * @param rechargeAppletRequest 接口参数
     * @return 充值结果
     */
    @SuppressWarnings("unchecked")
    @Transactional
    @Override
    public AccountRechargeAppletResponse rechargeAssetAccountApplet(HttpServletRequest request, RechargeAppletRequest rechargeAppletRequest) {
        String jsCode = rechargeAppletRequest.getJsCode();
        Double money = rechargeAppletRequest.getMoney();
        Long memberAssetAccountId = rechargeAppletRequest.getMemberAssetAccountId();
        MemberAssetAccount memberAssetAccount = memberAssetAccountRepository.findById(memberAssetAccountId).orElse(null);
        if (memberAssetAccount != null) {
            //校验账户
            this.checkMemberAssetAccount(memberAssetAccount);

            //交易订单号
            String tradeCode = SerialNumberUtils.getNumber(redisStringUtils, Constants.ACCOUNT_TRACE_CODE, Constants.REDIS_ORDER_INDEX, Constants.ACCOUNT_TRACE_CODE_DATE, Constants.ACCOUNT_TRACE_CODE_NUM_LEN);
            DecimalFormat decimalFormat = new DecimalFormat("#.00");

            //获取会员支付参数
            Long parentMemberId = memberAssetAccount.getParentMemberId();
            Long parentMemberRoleId = memberAssetAccount.getParentMemberRoleId();

            MobilePayRequest mobilePayRequest = new MobilePayRequest();
            mobilePayRequest.setOrderCode(tradeCode);
            mobilePayRequest.setPayMoney(Double.parseDouble(decimalFormat.format(money)));
            mobilePayRequest.setRemark(TradeOperationEnum.AccountRecharge.getMessage());
            mobilePayRequest.setServiceType(ServiceTypeEnum.Pay_Recharge.getCode());
            mobilePayRequest.setMemberId(parentMemberId);
            mobilePayRequest.setMemberRoleId(parentMemberRoleId);

            //支付
            PayResult payResult;
            Wrapper<PaymentParameterFeignDetailVO> parameterResult;
            Integer memberLevelType = memberAssetAccount.getMemberLevelType();
            if (MemberLevelTypeEnum.PLATFORM.getCode().equals(memberLevelType)) {
                mobilePayRequest.setPayType(PayTypeEnum.Platform.getCode());
                OrderPayChannelFeignVO feignVO = new OrderPayChannelFeignVO();
                feignVO.setPayChannel(OrderPayChannelEnum.WECHAT_PAY);
                parameterResult = orderFeignService.findPlatformPaymentParameters(feignVO);
            } else {
                mobilePayRequest.setPayType(PayTypeEnum.Member.getCode());
                OrderPayParameterFeignVO feignVO = new OrderPayParameterFeignVO();
                feignVO.setMemberId(parentMemberId);
                feignVO.setRoleId(parentMemberRoleId);
                feignVO.setPayChannel(OrderPayChannelEnum.WECHAT_PAY);
                parameterResult = orderFeignService.findMemberPaymentParameters(feignVO);
            }

            if(CollectionUtils.isEmpty(parameterResult.getData().getParameters())) {
                throw new BusinessException(ResponseCode.PAY_PLATFORM_PARAMETERS_DOES_NOT_EXIST);
            }

            parameterResult.getData().getParameters().forEach(p -> {
                if(p.getParameter().equals(OrderPaymentParameterEnum.WECHAT_MERCHANT_ID)) {
                    mobilePayRequest.setMerchantId(p.getValue());
                } else if(p.getParameter().equals(OrderPaymentParameterEnum.WECHAT_API_KEY)) {
                    mobilePayRequest.setApiKey(p.getValue());
                } else if(p.getParameter().equals(OrderPaymentParameterEnum.WECHAT_APPLET_APP_ID)) {
                    mobilePayRequest.setAppletAppId(p.getValue());
                } else if(p.getParameter().equals(OrderPaymentParameterEnum.WECHAT_APPLET_APP_KEY)) {
                    mobilePayRequest.setAppletAppKey(p.getValue());
                }
            });

            mobilePayRequest.setJsCode(jsCode);
            payResult = weChatPayService.jsAPIPay(mobilePayRequest, request);
            if (payResult.isSuccess()) {
                //保存交易记录
                AccountTradeRecord accountTradeRecord = new AccountTradeRecord();
                accountTradeRecord.setTradeCode(tradeCode);
                accountTradeRecord.setTradeMoney(money);
                accountTradeRecord.setMemberAssetAccount(memberAssetAccount);
                accountTradeRecord.setOperation(TradeOperationEnum.AccountRecharge.getCode());
                accountTradeRecord.setStatus(TradeStatusEnum.Paying.getCode());
                accountTradeRecord.setRemark(TradeOperationEnum.AccountRecharge.getMessage());
                accountTradeRecord.setTradeTime(System.currentTimeMillis());
                accountTradeRecordRepository.saveAndFlush(accountTradeRecord);

                //发送消息到队列(2小时)
                Long accountTradeRecordId = accountTradeRecord.getId();
                rabbitMQUtils.sendMsg(MessageConstants.pay_recharge_exchange, MessageConstants.pay_recharge_routingKey, accountTradeRecordId, 7200 * 1000);

                //支付返回结果
                Map<String, String> body = (Map<String, String>) payResult.getBody();
                AccountRechargeAppletResponse accountRechargeAppletResponse = new AccountRechargeAppletResponse();
                accountRechargeAppletResponse.setAppId(body.get("appId"));
                accountRechargeAppletResponse.setNoncestr(body.get("nonceStr"));
                accountRechargeAppletResponse.setPrepayid(body.get("package"));
                accountRechargeAppletResponse.setSignType(body.get("signType"));
                accountRechargeAppletResponse.setSign(body.get("paySign"));
                accountRechargeAppletResponse.setTimestamp(body.get("timeStamp"));
                accountRechargeAppletResponse.setTradeRecordId(accountTradeRecordId);
                return accountRechargeAppletResponse;
            } else {
                throw new BusinessException(ResponseCode.PAY_MEMBER_PAY_FAIL, payResult.getMessage());
            }
        } else {
            throw new BusinessException(ResponseCode.PAY_MEMBER_ASSET_ACCOUNT_NOT_EXIST);
        }
    }

    /**
     * 查询账户是否可用
     * @param tradeRecordId 交易记录Id
     * @return 是-true，否-false
     */
    @Override
    public Boolean getRechargeResult(Long tradeRecordId) {
        AccountTradeRecord accountTradeRecord = accountTradeRecordRepository.findById(tradeRecordId).orElse(null);
        return accountTradeRecord != null && TradeStatusEnum.ConfirmAccount.getCode().equals(accountTradeRecord.getStatus());
    }

    /**
     * 支付回调
     * @param out_trade_no 交易单号
     * @param trade_no 支付平台订单号
     */
    @Transactional
    @Override
    public void payNotify(String out_trade_no, String trade_no) {
        AccountTradeRecord accountTradeRecord = accountTradeRecordRepository.findFirstByTradeCode(out_trade_no);
        if (accountTradeRecord != null) {
            //更新交易记录
            accountTradeRecord.setStatus(TradeStatusEnum.ConfirmAccount.getCode());
            accountTradeRecord.setPayPlatformTradeCode(trade_no);
            accountTradeRecordRepository.saveAndFlush(accountTradeRecord);
            //获取交易金额
            Double tradeMoney = accountTradeRecord.getTradeMoney();

            //更新账户信息
            MemberAssetAccount memberAssetAccount = accountTradeRecord.getMemberAssetAccount();
            //校验账号
            this.checkMemberAssetAccount(memberAssetAccount);
            Double accountBalance = memberAssetAccount.getAccountBalance();
            DecimalFormat decimalFormat = new DecimalFormat("#.00");
            Double accountBalanceMoney = Double.parseDouble(decimalFormat.format(accountBalance + tradeMoney));
            memberAssetAccount.setAccountBalance(accountBalanceMoney);
            memberAssetAccount.setAccountBalanceEncrypt(DigestUtils.md5DigestAsHex(String.valueOf(accountBalanceMoney).getBytes()));
            memberAssetAccountRepository.saveAndFlush(memberAssetAccount);

        }
    }

    /**
     * 更新交易记录为支付失败
     * @param accountTradeRecordId 交易记录id
     */
    @Override
    public void updateAccountTradeRecordPayingFail(Long accountTradeRecordId) {
        AccountTradeRecord accountTradeRecord = accountTradeRecordRepository.findById(accountTradeRecordId).orElse(null);
        if (accountTradeRecord != null) {
            Integer status = accountTradeRecord.getStatus();
            if (TradeStatusEnum.Paying.getCode().equals(status)) {
                accountTradeRecord.setStatus(TradeStatusEnum.PayingFail.getCode());
                accountTradeRecordRepository.saveAndFlush(accountTradeRecord);
            }
        }
    }

    /**
     * 资金账户提现
     * @param cashOutRequest 接口参数
     * @return 提示信息
     */
    @Transactional
    @Override
    public String cashOutAssetAccount(CashOutRequest cashOutRequest) {
        Long memberAssetAccountId = cashOutRequest.getMemberAssetAccountId();
        DecimalFormat decimalFormat = new DecimalFormat("#.00");
        Double money = Double.parseDouble(decimalFormat.format(cashOutRequest.getMoney()));
        MemberAssetAccount memberAssetAccount = memberAssetAccountRepository.findById(memberAssetAccountId).orElse(null);
        if (memberAssetAccount != null) {
            //校验账户
            this.checkMemberAssetAccount(memberAssetAccount);
            //判断交易金额
            Double accountBalance = memberAssetAccount.getAccountBalance();
            Double lockBalance = memberAssetAccount.getLockBalance();
            if (money > (accountBalance - lockBalance)) {
                throw new BusinessException(ResponseCode.PAY_MEMBER_ASSET_ACCOUNT_MORE_EXCEPTION);
            }

            //保存账户信息
            Double lockMoney = Double.parseDouble(decimalFormat.format(money + lockBalance));
            memberAssetAccount.setAccountBalance(accountBalance);
            memberAssetAccount.setAccountBalanceEncrypt(DigestUtils.md5DigestAsHex(String.valueOf(accountBalance).getBytes()));
            memberAssetAccount.setLockBalance(lockMoney);
            memberAssetAccount.setLockBalanceEncrypt(DigestUtils.md5DigestAsHex(String.valueOf(lockMoney).getBytes()));
            memberAssetAccountRepository.saveAndFlush(memberAssetAccount);

            //保存交易记录
            AccountTradeRecord accountTradeRecord = new AccountTradeRecord();
            accountTradeRecord.setTradeCode(SerialNumberUtils.getNumber(redisStringUtils, Constants.ACCOUNT_TRACE_CODE, Constants.REDIS_ORDER_INDEX, Constants.ACCOUNT_TRACE_CODE_DATE, Constants.ACCOUNT_TRACE_CODE_NUM_LEN));
            accountTradeRecord.setTradeMoney(money);
            accountTradeRecord.setOperation(TradeOperationEnum.AccountCashOut.getCode());
            accountTradeRecord.setStatus(TradeStatusEnum.ApplyCashOut.getCode());
            accountTradeRecord.setMemberAssetAccount(memberAssetAccount);
            accountTradeRecord.setRemark(TradeOperationEnum.AccountCashOut.getMessage());
            accountTradeRecord.setTradeTime(System.currentTimeMillis());
            accountTradeRecord.setBankName(cashOutRequest.getBankName());
            accountTradeRecord.setBankAccount(cashOutRequest.getBankAccount());
            accountTradeRecord.setBankAccountName(cashOutRequest.getBankAccountName());
            accountTradeRecordRepository.saveAndFlush(accountTradeRecord);

            //首页数据统计
            try {
                //待审核提现
                OperateNoticeVO operateNoticeVO = new OperateNoticeVO();
                operateNoticeVO.setMemberId(memberAssetAccount.getParentMemberId());
                operateNoticeVO.setRoleId(memberAssetAccount.getParentMemberRoleId());
                operateNoticeVO.setDataSource(OperateDataSourceEnum.ACCOUNT.getCode());
                operateNoticeVO.setIncreaseOperateType(AccountOperateTypeEnum.TO_BE_VALIFY_CASHOUT.getCode());
                operateNoticeVO.setIncreaseCount(1L);
                reportControllerFeign.addOperateNotice(operateNoticeVO);

                //发送消息
                SystemMessageRequest systemMessageRequest = new SystemMessageRequest();
                if (MemberLevelTypeEnum.PLATFORM.getCode().equals(memberAssetAccount.getMemberLevelType())) {
                    // 平台会员
                    systemMessageRequest.setMemberId(0L);
                    systemMessageRequest.setRoleId(0L);
                    systemMessageRequest.setMessageNotice(MessageTemplateCode.withdraw_platform_wait_audit);
                    systemMessageRequest.setParams(Collections.singletonList(memberAssetAccount.getMemberName()));
                } else {
                    // 普通会员
                    systemMessageRequest.setMemberId(memberAssetAccount.getParentMemberId());
                    systemMessageRequest.setRoleId(memberAssetAccount.getParentMemberRoleId());
                    systemMessageRequest.setMessageNotice(MessageTemplateCode.withdraw_wait_audit);
                    systemMessageRequest.setParams(Collections.singletonList(memberAssetAccount.getMemberName()));
                }
                systemMessageControllerFeign.sendSystemMessage(systemMessageRequest);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return "申请提现成功";
        }
        throw new BusinessException(ResponseCode.PAY_MEMBER_ASSET_ACCOUNT_NOT_EXIST);
    }

    /**
     * 支付提现
     * @param payRequest 接口参数
     */
    @Transactional
    @Override
    public String payCashOut(PayRequest payRequest) {
        Long id = payRequest.getId();
        AccountTradeRecord accountTradeRecord = accountTradeRecordRepository.findById(id).orElse(null);
        if (accountTradeRecord != null) {
            MemberAssetAccount memberAssetAccount = accountTradeRecord.getMemberAssetAccount();
            if (memberAssetAccount != null) {
                MemberAssetAccount assetAccount = this.getAccount(memberAssetAccount);
                memberAssetAccountRepository.saveAndFlush(assetAccount);

                //更新交易记录
                accountTradeRecord.setTradeTime(System.currentTimeMillis());
                accountTradeRecord.setStatus(TradeStatusEnum.CashOutSuccess.getCode());
                accountTradeRecordRepository.saveAndFlush(accountTradeRecord);

                //保存提现处理记录
                AccountCashOutRecord accountCashOutRecord = new AccountCashOutRecord();
                accountCashOutRecord.setTradeCode(accountTradeRecord.getTradeCode());
                accountCashOutRecord.setTradeMoney(accountTradeRecord.getTradeMoney());
                accountCashOutRecord.setOperation(accountTradeRecord.getOperation());
                accountCashOutRecord.setRemark(payRequest.getRemark());
                accountCashOutRecord.setPayType(payRequest.getPayType());
                accountCashOutRecord.setPayChannel(payRequest.getPayChannel());
                accountCashOutRecord.setStatus(TradeStatusEnum.CashOutSuccess.getCode());
                accountCashOutRecord.setTradeTime(System.currentTimeMillis());
                accountCashOutRecordRepository.saveAndFlush(accountCashOutRecord);

                try {

                    //待支付提现
                    OperateNoticeVO operateNoticeVO = new OperateNoticeVO();
                    operateNoticeVO.setMemberId(assetAccount.getParentMemberId());
                    operateNoticeVO.setRoleId(assetAccount.getParentMemberRoleId());
                    operateNoticeVO.setDataSource(OperateDataSourceEnum.ACCOUNT.getCode());
                    operateNoticeVO.setReduceOperateType(AccountOperateTypeEnum.TO_BE_PAY_CASHOUT.getCode());
                    operateNoticeVO.setReduceCount(1L);
                    reportControllerFeign.addOperateNotice(operateNoticeVO);

                    //发送消息
                    SystemMessageRequest systemMessageRequest = new SystemMessageRequest();
                    systemMessageRequest.setMemberId(assetAccount.getMemberId());
                    systemMessageRequest.setRoleId(assetAccount.getMemberRoleId());
                    systemMessageRequest.setMessageNotice(MessageTemplateCode.withdraw_audit);
                    systemMessageRequest.setParams(Collections.singletonList("支付成功"));
                    systemMessageControllerFeign.sendSystemMessage(systemMessageRequest);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return "支付成功";
            } else {
                throw new BusinessException(ResponseCode.PAY_MEMBER_ASSET_ACCOUNT_NOT_EXIST);
            }
        } else {
            throw new BusinessException(ResponseCode.PAY_MEMBER_ASSET_ACCOUNT_PAY_NOT_EXIST);
        }
    }

    /**
     * 余额支付
     * @param balancePayRequest 支付接口参数
     * @return 支付交易号
     */
    @Transactional
    @Override
    public String balancePay(BalancePayRequest balancePayRequest) {
        logger.info("余额支付接收到参数 => " + payCacheService.serializeObject(balancePayRequest));

        Long memberId = balancePayRequest.getMemberId();
        Long memberRoleId = balancePayRequest.getMemberRoleId();
        Long parentMemberId = balancePayRequest.getParentMemberId();
        Long parentMemberRoleId = balancePayRequest.getParentMemberRoleId();
        String payPassword = balancePayRequest.getPayPassword();
        Double payMoney = balancePayRequest.getPayMoney();
        String remark = balancePayRequest.getRemark();
        Integer payType = balancePayRequest.getPayType();
        String orderCode = balancePayRequest.getOrderCode();
        //查询账户信息
        MemberAssetAccount memberAssetAccount;
        if (payType.equals(PayTypeEnum.Platform.getCode())) {
            memberAssetAccount = memberAssetAccountRepository.findFirstByMemberIdAndMemberRoleIdAndMemberLevelType(memberId, memberRoleId, MemberLevelTypeEnum.PLATFORM.getCode());
        } else {
            memberAssetAccount = memberAssetAccountRepository.findFirstByMemberIdAndMemberRoleIdAndParentMemberIdAndParentMemberRoleId(memberId, memberRoleId, parentMemberId, parentMemberRoleId);
        }

        if(memberAssetAccount == null) {
            throw new BusinessException(ResponseCode.PAY_MEMBER_ASSET_ACCOUNT_NOT_EXIST);
        }

        //检验账户
        this.checkMemberAssetAccount(memberAssetAccount);
        //检验支付密码
        this.checkMemberPayPassword(memberId, payPassword);
        //检验支付金额
        Double accountBalance = memberAssetAccount.getAccountBalance();
        if (accountBalance - memberAssetAccount.getLockBalance() < payMoney) {
            throw new BusinessException(ResponseCode.PAY_MEMBER_ASSET_ACCOUNT_MORE_EXCEPTION);
        }

        //四舍五入，保留两位小数
        DecimalFormat decimalFormat = new DecimalFormat("#.00");
        Double accountBalanceMoney = Double.parseDouble(decimalFormat.format(accountBalance - payMoney));
        memberAssetAccount.setAccountBalance(accountBalanceMoney);
        memberAssetAccount.setAccountBalanceEncrypt(DigestUtils.md5DigestAsHex(String.valueOf(accountBalanceMoney).getBytes()));
        memberAssetAccountRepository.saveAndFlush(memberAssetAccount);

        //保存交易记录
        String tradeCode = SerialNumberUtils.getNumber(redisStringUtils, Constants.ACCOUNT_TRACE_CODE, Constants.REDIS_ORDER_INDEX, Constants.ACCOUNT_TRACE_CODE_DATE, Constants.ACCOUNT_TRACE_CODE_NUM_LEN);
        AccountTradeRecord accountTradeRecord = new AccountTradeRecord();
        accountTradeRecord.setMemberAssetAccount(memberAssetAccount);
        accountTradeRecord.setTradeCode(tradeCode);
        accountTradeRecord.setTradeMoney(payMoney);
        accountTradeRecord.setOperation(TradeOperationEnum.OrderPay.getCode());
        accountTradeRecord.setStatus(TradeStatusEnum.PayingSuccess.getCode());
        accountTradeRecord.setRemark(remark);
        accountTradeRecord.setTradeTime(System.currentTimeMillis());
        accountTradeRecord.setPayPlatformTradeCode(orderCode);
        accountTradeRecordRepository.saveAndFlush(accountTradeRecord);
        return tradeCode;
    }

    /**
     * 余额返现
     * @param balanceCashbackRequest 接口参数
     * @return 交易流水号
     */
    @Transactional
    @Override
    public String balanceCashback(BalanceCashbackRequest balanceCashbackRequest) {
        Long memberId = balanceCashbackRequest.getMemberId();
        Long memberRoleId = balanceCashbackRequest.getMemberRoleId();
        Long parentMemberId = balanceCashbackRequest.getParentMemberId();
        Long parentMemberRoleId = balanceCashbackRequest.getParentMemberRoleId();
        Double cashbackMoney = balanceCashbackRequest.getCashbackMoney();
        String remark = balanceCashbackRequest.getRemark();
        Integer cashbackType = balanceCashbackRequest.getCashbackType();
        String orderCode = balanceCashbackRequest.getOrderCode();

        //查询账户信息
        MemberAssetAccount memberAssetAccount;
        if (PayTypeEnum.Platform.getCode().equals(cashbackType)) {
            memberAssetAccount = memberAssetAccountRepository.findFirstByMemberIdAndMemberRoleIdAndMemberLevelType(memberId, memberRoleId, MemberLevelTypeEnum.PLATFORM.getCode());
        } else {
            memberAssetAccount = memberAssetAccountRepository.findFirstByMemberIdAndMemberRoleIdAndParentMemberIdAndParentMemberRoleId(memberId, memberRoleId, parentMemberId, parentMemberRoleId);
        }

        if(memberAssetAccount == null) {
            throw new BusinessException(ResponseCode.PAY_MEMBER_ASSET_ACCOUNT_NOT_EXIST);
        }

        //检验账户
        this.checkMemberAssetAccount(memberAssetAccount);
        //返现金额
        Double accountBalance = memberAssetAccount.getAccountBalance();
        //四舍五入，保留两位小数
        DecimalFormat decimalFormat = new DecimalFormat("#.00");
        Double accountBalanceMoney = Double.parseDouble(decimalFormat.format(accountBalance + cashbackMoney));
        memberAssetAccount.setAccountBalance(accountBalanceMoney);
        memberAssetAccount.setAccountBalanceEncrypt(DigestUtils.md5DigestAsHex(String.valueOf(accountBalanceMoney).getBytes()));
        memberAssetAccountRepository.saveAndFlush(memberAssetAccount);

        //保存交易记录
        String tradeCode = SerialNumberUtils.getNumber(redisStringUtils, Constants.ACCOUNT_TRACE_CODE, Constants.REDIS_ORDER_INDEX, Constants.ACCOUNT_TRACE_CODE_DATE, Constants.ACCOUNT_TRACE_CODE_NUM_LEN);
        AccountTradeRecord accountTradeRecord = new AccountTradeRecord();
        accountTradeRecord.setMemberAssetAccount(memberAssetAccount);
        accountTradeRecord.setTradeCode(tradeCode);
        accountTradeRecord.setTradeMoney(cashbackMoney);
        accountTradeRecord.setOperation(TradeOperationEnum.OrderRebate.getCode());
        accountTradeRecord.setStatus(TradeStatusEnum.ConfirmAccount.getCode());
        accountTradeRecord.setRemark(remark);
        accountTradeRecord.setTradeTime(System.currentTimeMillis());
        accountTradeRecord.setPayPlatformTradeCode(orderCode);
        accountTradeRecordRepository.saveAndFlush(accountTradeRecord);
        return tradeCode;
    }

    /**
     * 余额退款
     * @param balanceRefundRequest 接口参数
     * @return 退款是否成功
     */
    @Transactional
    @Override
    public Boolean balanceRefund(BalanceRefundRequest balanceRefundRequest) {
        logger.info("余额退款接收到参数 => " + payCacheService.serializeObject(balanceRefundRequest));

        Double tradeMoney = balanceRefundRequest.getTradeMoney();
        String payPlatformTradeCode = balanceRefundRequest.getPayPlatformTradeCode();
        String remark = balanceRefundRequest.getRemark();
        List<AccountTradeRecord> accountTradeRecordList =  accountTradeRecordRepository.findByPayPlatformTradeCodeAndOperationAndStatus(payPlatformTradeCode, TradeOperationEnum.OrderPay.getCode(), TradeStatusEnum.PayingSuccess.getCode());
        if (accountTradeRecordList != null && !accountTradeRecordList.isEmpty()) {
            if (accountTradeRecordList.size() == 1) {
                AccountTradeRecord accountTradeRecord = accountTradeRecordList.get(0);
                MemberAssetAccount memberAssetAccount = accountTradeRecord.getMemberAssetAccount();
                this.checkMemberAssetAccount(memberAssetAccount);
                Double accountBalance = memberAssetAccount.getAccountBalance();
                DecimalFormat decimalFormat = new DecimalFormat("#.00");
                Double accountBalanceMoney = Double.parseDouble(decimalFormat.format(accountBalance + tradeMoney));
                String accountBalanceEncrypt = DigestUtils.md5DigestAsHex(String.valueOf(accountBalanceMoney).getBytes());
                memberAssetAccount.setAccountBalance(accountBalanceMoney);
                memberAssetAccount.setAccountBalanceEncrypt(accountBalanceEncrypt);
                memberAssetAccountRepository.saveAndFlush(memberAssetAccount);

                //保存交易记录
                String tradeCode = SerialNumberUtils.getNumber(redisStringUtils, Constants.ACCOUNT_TRACE_CODE, Constants.REDIS_ORDER_INDEX, Constants.ACCOUNT_TRACE_CODE_DATE, Constants.ACCOUNT_TRACE_CODE_NUM_LEN);
                accountTradeRecord = new AccountTradeRecord();
                accountTradeRecord.setMemberAssetAccount(memberAssetAccount);
                accountTradeRecord.setTradeCode(tradeCode);
                accountTradeRecord.setTradeMoney(tradeMoney);
                accountTradeRecord.setOperation(TradeOperationEnum.OrderRefund.getCode());
                accountTradeRecord.setStatus(TradeStatusEnum.ConfirmAccount.getCode());
                accountTradeRecord.setRemark(remark);
                accountTradeRecord.setTradeTime(System.currentTimeMillis());
                accountTradeRecord.setPayPlatformTradeCode(payPlatformTradeCode);
                accountTradeRecordRepository.saveAndFlush(accountTradeRecord);
                return true;
            } else {
                throw new BusinessException(ResponseCode.PAY_MEMBER_ASSET_ACCOUNT_TRADE_RECORD_EXCEPTION);
            }
        } else {
            throw new BusinessException(ResponseCode.PAY_MEMBER_ASSET_ACCOUNT_TRADE_RECORD_NOT_EXIST);
        }
    }

    /**
     * 查询登录用户的账户余额
     * @param fundMode 资金归集模式: 1-平台代收; 2-会员直接到账
     * @param parentMemberId 上级会员id
     * @param parentMemberRoleId 上级会员角色id
     */
    @Override
    public Double getUserBalance(Integer fundMode, Long memberId, Long memberRoleId, Long parentMemberId, Long parentMemberRoleId) {
        //查询账户信息
        MemberAssetAccount memberAssetAccount;
        if (fundMode.equals(PayTypeEnum.Platform.getCode())) {
            memberAssetAccount = memberAssetAccountRepository.findFirstByMemberIdAndMemberRoleIdAndMemberLevelType(memberId, memberRoleId, MemberLevelTypeEnum.PLATFORM.getCode());
        } else {
            memberAssetAccount = memberAssetAccountRepository.findFirstByMemberIdAndMemberRoleIdAndParentMemberIdAndParentMemberRoleId(memberId, memberRoleId, parentMemberId, parentMemberRoleId);
        }

        if(memberAssetAccount == null) {
            throw new BusinessException(ResponseCode.PAY_MEMBER_ASSET_ACCOUNT_NOT_EXIST);
        }

        //检验账户
        this.checkMemberAssetAccount(memberAssetAccount);
        //四舍五入，保留两位小数
        DecimalFormat decimalFormat = new DecimalFormat("#.00");
        return Double.parseDouble(decimalFormat.format(memberAssetAccount.getAccountBalance() - memberAssetAccount.getLockBalance()));
    }

    /**
     * 查询采购商的账户余额
     * @param childMemberId 下级会员id
     * @param childMemberRoleId 下级会员角色id
     */
    @Override
    public Double getChildUserBalance(Long memberId, Long memberRoleId, Long childMemberId, Long childMemberRoleId) {
        //查询账户信息
        MemberAssetAccount memberAssetAccount = memberAssetAccountRepository.findFirstByMemberIdAndMemberRoleIdAndParentMemberIdAndParentMemberRoleId(childMemberId, childMemberRoleId, memberId, memberRoleId);

        if(memberAssetAccount == null) {
            throw new BusinessException(ResponseCode.PAY_MEMBER_ASSET_ACCOUNT_NOT_EXIST);
        }

        //检验账户
        this.checkMemberAssetAccount(memberAssetAccount);
        //四舍五入，保留两位小数
        DecimalFormat decimalFormat = new DecimalFormat("#.00");
        return Double.parseDouble(decimalFormat.format(memberAssetAccount.getAccountBalance() - memberAssetAccount.getLockBalance()));
    }

    /**
     * 查询登录用户的所有账户余额
     * @param memberId 会员Id
     * @param memberRoleId 会员角色Id
     * @return 所有账户余额的和
     */
    @Override
    public Double getUserAllBalance(Long memberId, Long memberRoleId) {
        List<MemberAssetAccount> memberAssetAccountList = memberAssetAccountRepository.findByMemberIdAndMemberRoleId(memberId, memberRoleId);
        return memberAssetAccountList.stream().map(memberAssetAccount -> {
            //检验账户
            this.checkMemberAssetAccount(memberAssetAccount);
            //四舍五入，保留两位小数
            DecimalFormat decimalFormat = new DecimalFormat("#.00");
            return Double.parseDouble(decimalFormat.format(memberAssetAccount.getAccountBalance() - memberAssetAccount.getLockBalance()));
        }).collect(Collectors.summarizingDouble(value -> value)).getSum();
    }

    /**
     * 查询平台账户详情
     */
    @Override
    public MemberAssetAccount getPlatFormAssetAccount(UserLoginCacheDTO sysUser) {
        List<MemberAssetAccount> memberAssetAccountList = memberAssetAccountRepository.findByMemberIdAndMemberRoleId(sysUser.getMemberId(), sysUser.getMemberRoleId());
        for(MemberAssetAccount memberAssetAccount : memberAssetAccountList){
            Integer memberLevelType = memberAssetAccount.getMemberLevelType();
            if(MemberLevelTypeEnum.PLATFORM.getCode().equals(memberLevelType)){
                return memberAssetAccount;
            }
        }
        throw new BusinessException(ResponseCode.PAY_MEMBER_ASSET_ACCOUNT_NOT_EXIST);
    }

    /**
     * 查询会员用户的账户详情
     * @param memberId              登录用户会员id
     * @param memberRoleId          登录用户会员角色id
     * @param parentMemberId        上级会员id
     * @param parentMemberRoleId    上级会员角色id
     * @return  账户详情
     */
    @Override
    public MemberAssetAccountResponse getUserAssetAccount(Long memberId, Long memberRoleId, Long parentMemberId, Long parentMemberRoleId) {
        List<MemberAssetAccount> memberAssetAccountList = memberAssetAccountRepository.findByMemberIdAndMemberRoleIdAndParentMemberIdAndParentMemberRoleId(memberId, memberRoleId, parentMemberId, parentMemberRoleId);
        if(memberAssetAccountList != null && memberAssetAccountList.size() > 0){
            if(memberAssetAccountList.size() == 1){
                MemberAssetAccount assetAccount = memberAssetAccountList.get(0);
                return BeanUtil.copyProperties(assetAccount, MemberAssetAccountResponse.class);
            }else{
                throw new BusinessException(ResponseCode.PAY_MEMBER_ASSET_ACCOUNT_EXCEPTION);
            }
        }
        throw new BusinessException(ResponseCode.PAY_MEMBER_ASSET_ACCOUNT_NOT_EXIST);
    }

    /**
     * 统一检验账户
     */
    @Override
    public void checkMemberAssetAccount(MemberAssetAccount memberAssetAccount) {
        //验证会员状态
        Integer memberStatus = memberAssetAccount.getMemberStatus();
        if (!MemberStatusEnum.NORMAL.getCode().equals(memberStatus)) {
            throw new BusinessException(ResponseCode.PAY_MEMBER_STATUS_EXCEPTION);
        }
        //验证会员账户状态
        Integer accountStatus = memberAssetAccount.getAccountStatus();
        if (!AccountStatusEnum.Thaw.getCode().equals(accountStatus)) {
            throw new BusinessException(ResponseCode.PAY_MEMBER_ASSET_ACCOUNT_STATUS_EXCEPTION);
        }
        //验证金额
        Double account = memberAssetAccount.getAccountBalance();
        Double lock = memberAssetAccount.getLockBalance();
        String accountBalance = DigestUtils.md5DigestAsHex(String.valueOf(account).getBytes());
        String accountBalanceEncrypt = memberAssetAccount.getAccountBalanceEncrypt();
        String lockBalance = DigestUtils.md5DigestAsHex(String.valueOf(lock).getBytes());
        String lockBalanceEncrypt = memberAssetAccount.getLockBalanceEncrypt();
        if (!accountBalance.equals(accountBalanceEncrypt) || !lockBalance.equals(lockBalanceEncrypt)) {
            throw new BusinessException(ResponseCode.PAY_MEMBER_ASSET_ACCOUNT_MONEY_EXCEPTION);
        }
    }

    /**
     * 统一验证支付密码
     */
    private void checkMemberPayPassword(Long memberId, String password) {
        // 校验支付密码
        MemberFeignPayPswCheckVO checkVO = new MemberFeignPayPswCheckVO();
        checkVO.setMemberId(memberId);
        checkVO.setPayPassword(password);
        Wrapper<MemberFeignPayPswCheckResultVO> checkResultVOWrapper = memberInnerControllerFeign.checkMemberPayPassword(checkVO);
        if (checkResultVOWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            throw new BusinessException(ResponseCode.getByCode(checkResultVOWrapper.getCode()));
        }

        if (!checkResultVOWrapper.getData().getCheckResult().equals(MemberPayPasswordCheckEnum.CORRECT.getCode())) {
            // 支付密码未设置
            if (checkResultVOWrapper.getData().getCheckResult().equals(MemberPayPasswordCheckEnum.NOT_SET.getCode())) {
                throw new BusinessException(ResponseCode.PAY_CREDIT_PASSWORD_NOT_SET);
            }
            // 支付密码错误
            else if (checkResultVOWrapper.getData().getCheckResult().equals(MemberPayPasswordCheckEnum.INCORRECT.getCode())) {
                throw new BusinessException(ResponseCode.PAY_CREDIT_PASSWORD_INCORRECT);
            }
            // 支付状态未知时，返回服务内部错误
            else {
                throw new BusinessException(ResponseCode.BUSINESS_ERROR);
            }
        }
    }

    /**
     * 计算资金
     * @param memberAssetAccount 接口参数
     * @return 计算结果
     */
    private MemberAssetAccount getAccount(MemberAssetAccount memberAssetAccount) {
        Double account = memberAssetAccount.getAccountBalance();
        Double lock = memberAssetAccount.getLockBalance();
        //检验账户
        this.checkMemberAssetAccount(memberAssetAccount);
        //计算余额和锁定金额
        Double defaultMoney = 0.00;
        String defaultMoneyEncrypt = DigestUtils.md5DigestAsHex(String.valueOf(defaultMoney).getBytes());
        memberAssetAccount.setLockBalance(defaultMoney);
        memberAssetAccount.setLockBalanceEncrypt(defaultMoneyEncrypt);

        //四舍五入，保留两位小数
        DecimalFormat decimalFormat = new DecimalFormat("#.00");
        Double accountBalanceMoney = Double.parseDouble(decimalFormat.format(account - lock));
        memberAssetAccount.setAccountBalance(accountBalanceMoney);
        memberAssetAccount.setAccountBalanceEncrypt(DigestUtils.md5DigestAsHex(String.valueOf(accountBalanceMoney).getBytes()));
        return memberAssetAccount;
    }

    /**
     * 构建查询条件
     * @param memberAssetAccountMiddle 接口参数
     * @return 查询条件
     */
    private Specification<MemberAssetAccount> getSpecification(MemberAssetAccountQuery memberAssetAccountMiddle) {
        return (Specification<MemberAssetAccount>) (root, query, criteriaBuilder) -> {
            Predicate finalConditions = criteriaBuilder.conjunction();

            String parentMemberName = memberAssetAccountMiddle.getParentMemberName();
            Long parentMemberId = memberAssetAccountMiddle.getParentMemberId();
            Long parentMemberRoleId = memberAssetAccountMiddle.getParentMemberRoleId();
            String memberName = memberAssetAccountMiddle.getMemberName();
            Long memberId = memberAssetAccountMiddle.getMemberId();
            Long memberRoleId = memberAssetAccountMiddle.getMemberRoleId();
            Integer memberType = memberAssetAccountMiddle.getMemberType();
            List<Integer> memberLevelTypeList = memberAssetAccountMiddle.getMemberLevelTypeList();
            Integer memberStatus = memberAssetAccountMiddle.getMemberStatus();
            Integer accountStatus = memberAssetAccountMiddle.getAccountStatus();
            Long startTime = memberAssetAccountMiddle.getStartTime();
            Long endTime = memberAssetAccountMiddle.getEndTime();
            Boolean enableMultiTenancy = memberAssetAccountMiddle.getEnableMultiTenancy();

            //上级会员名称
            if (StringUtils.hasLength(parentMemberName)) {
                finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.like(root.get("parentMemberName").as(String.class), "%" + parentMemberName + "%"));
            }
            //上级会员id
            if (parentMemberId != null && parentMemberId > 0) {
                finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("parentMemberId").as(Long.class), parentMemberId));
            }
            //上级会员角色id
            if (parentMemberRoleId != null && parentMemberRoleId > 0) {
                finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("parentMemberRoleId").as(Long.class), parentMemberRoleId));
            }
            //会员名称
            if (StringUtils.hasLength(memberName)) {
                finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.like(root.get("memberName").as(String.class), "%" + memberName + "%"));
            }
            //会员id
            if (memberId != null && memberId > 0) {
                finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("memberId").as(Long.class), memberId));
            }
            //会员角色id
            if (memberRoleId != null && memberRoleId > 0) {
                finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("memberRoleId").as(Long.class), memberRoleId));
            }
            //会员类型
            if (memberType != null && memberType > 0) {
                finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("memberType").as(Integer.class), memberType));
            }
            //会员等级类型
            if (memberLevelTypeList != null && !memberLevelTypeList.isEmpty()) {
                finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.in(root.get("memberLevelType")).value(memberLevelTypeList));
            }
            //如果开启SaaS多租户,则不筛选会员等级类型为平台会员的数据
            if (enableMultiTenancy){
                finalConditions=criteriaBuilder.and(finalConditions,criteriaBuilder.notEqual(root.get("memberLevelType").as(Integer.class), MemberLevelTypeEnum.PLATFORM.getCode()));
            }
            //会员状态
            if (memberStatus != null && memberStatus > 0) {
                finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("memberStatus").as(Integer.class), memberStatus));
            }
            //账号状态
            if (accountStatus != null && accountStatus > 0) {
                finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("accountStatus").as(Integer.class), accountStatus));
            }
            //开始时间
            if (startTime != null && startTime > 0) {
                finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.ge(root.get("createTime"), startTime));
            }
            //结束时间
            if (endTime != null && endTime > 0) {
                finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.le(root.get("createTime"), endTime));
            }
            return finalConditions;
        };
    }
}

